package com.ruoyi.walmart.http;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.*;
import com.alibaba.fastjson2.JSON;
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import com.opencsv.bean.HeaderColumnNameMappingStrategy;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.walmart.domain.Items.ItemReportCsv;
import com.ruoyi.walmart.domain.Items.ReportItem;
import com.ruoyi.walmart.domain.auth.ShopAuth;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;

import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

import static com.ruoyi.walmart.util.walmartUtil.getHeaders;

@Log4j2
public class WalmartRequest {

    // 从配置文件中获取固定路径
    @Value("${downloads.path}")
    private static String downloadsPath;

    /**
     * 发送get请求
     *
     * @param requestUrl 请求url,可带参数
     * @param paramMap   请求参数，根据请求方式区分，get会追加到url后,post则为json
     * @author senghor
     * @date 2022/5/12 16:48
     */
    public static String request(String requestUrl, Method method, Map<String, ?> paramMap, ShopAuth shopAuth) {

        HttpResponse response = null;
        try {
            if (Method.GET == method) {
                // get请求拼接参数
                if (paramMap != null && paramMap.size() > 0) {
                    if (requestUrl.indexOf("?") > 0) {
                        requestUrl = requestUrl + "&" + HttpUtil.toParams(paramMap);
                    } else {
                        requestUrl = requestUrl + "?" + HttpUtil.toParams(paramMap);
                    }
                }
            }
            Map<String, String> headers = getHeaders( requestUrl, method, paramMap,shopAuth);
            log.info("walmart本次请求路径:" + requestUrl);
            HttpRequest httpRequest = HttpRequest
                    .of(requestUrl)
                    .setMethod(method)
                    .addHeaders(headers)
                    .contentType(ContentType.JSON.getValue());
            response = httpRequest.execute();
            log.info("response body" + response.body());
            if (HttpStatus.HTTP_OK == response.getStatus()) {
                return isCsv(response) ? resolveCsv(response) : response.body();
            }else {
                throw new ServiceException("调用Walmart API 错误");
            }
        }  catch (Exception e) {
            log.error(requestUrl + "调用Walmart API 错误" + e.getMessage(), e);
            throw new ServiceException("调用Walmart API 异常:" + e);
        } finally {
            if (ObjectUtils.isNotEmpty(response)){
                response.close();
            }
        }
    }

    /**
     * 判断是否是csv文件
     *
     * @param response
     * @return
     */
    private static boolean isCsv(HttpResponse response) {
        String header = response.header("Content-Disposition");
        return StrUtil.isNotBlank(header) && header.contains("filename=");
    }

    /**
     * 解析cvs
     *
     * @param response
     */
    public static String resolveCsv(HttpResponse response) {
        InputStream inputStream = response.bodyStream();
        try {
            String header = getContentDisposition(response);
//            header value will be something like:
//            attachment; filename=10000000354_2016-01-15T23:09:54.438+0000.zip
            int length = header.length();
            String fileName = header.substring(header.indexOf("filename="), length);
            String[] str = fileName.split("=");
                File reportFile = getTemporaryFile(str[1]);
            OutputStream outStream = new FileOutputStream(getTemporaryFile(str[1]));
            byte[] buffer = new byte[16 * 1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outStream.write(buffer, 0, bytesRead);
            }
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outStream);
            return reportFile.getPath();
        } catch (Exception ex) {
            log.error("Exception: " + ex.getMessage(), ex);
        }
        return "";
    }

    private static String getContentDisposition(HttpResponse response) {
        return response.header("Content-Disposition");
    }

    private static File getTemporaryFile(String filename) {
        return new File("D:\\home\\walmart\\payment\\" + filename);
    }

    public static String requestPost(String url, Map<String, Object> paramMap,String jsonBody,ShopAuth shopAuth) {
        Map<String, String> headers = getHeaders(null,Method.POST,null,shopAuth);

        // post请求拼接参数
        if (paramMap != null && paramMap.size() > 0) {
            if (url.indexOf("?") > 0) {
                url = url + "&" + HttpUtil.toParams(paramMap);
            } else {
                url = url + "?" + HttpUtil.toParams(paramMap);
            }
        }

        HttpResponse response = HttpRequest.post(url)
                .addHeaders(headers)
                .body(jsonBody)
                .execute();

        if (HttpStatus.HTTP_OK == response.getStatus()) {
            log.info("接口响应数据response：{}", response);
            log.info("接口响应数据response.body()：{}", response.body());

            return response.body();
        } else if(429 == response.getStatus()){
            throw new ServiceException("您每小时只可以为每个报告类型请求一份报告，请稍后再试！");
        } else {
            String errorMessage = "调用Walmart API 异常: 状态码: " + response.getStatus() + ", 响应内容: " + response.body();
            log.error("调用Walmart API 错误");
            throw new ServiceException(errorMessage);  // 抛出带有错误消息的异常
        }
    }

    public static List<ReportItem> processFileFromURL(String url, String reportType, ShopAuth shopAuth, String requestId) {
        // 1.下载 ZIP 文件
        String path = downloadsPath;
        String prefix = UUID.randomUUID() + "-" + reportType;
        String fileName = prefix + ".zip";
        File file = new File(path + fileName);
        HttpUtil.downloadFile(url,file);
        // 2.读取 ZIP 文件
        ZipFile zipFile = null;
        BufferedInputStream inputStream = null;
        try {
            zipFile = new ZipFile(file);
            inputStream = FileUtil.getInputStream(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try (//转换成zip输入流
             ZipInputStream zipStream = new ZipInputStream(inputStream, CharsetUtil.defaultCharset());
        ) {
            ZipEntry zipEntry;
            //循环读取压缩包里面的文件
            while (null != (zipEntry = zipStream.getNextEntry())) {
                if (!zipEntry.isDirectory()) {
                    String name = zipEntry.getName();
                    if (name.endsWith("csv")) {
                        BufferedReader br = new BufferedReader(
                                new InputStreamReader(zipFile.getInputStream(zipEntry)));
                        // 打印 CSV 每一行内容，便于调试
//                        String line;
//                        while ((line = br.readLine()) != null) {
//                            // 清理反斜杠和不匹配的引号
//                            line = line.replaceAll("\\\\", "");  // 删除多余的反斜杠
//                            line = line.replaceAll("\"{2}", "\"");  // 替换双引号为单个引号
//                            line = line.trim();  // 去除行首尾的空格
//
//                            // 打印每行内容，帮助调试
//                            System.out.println("Parsing CSV line: " + line);
//                        }

                        if ("ITEM".equals(reportType)) {
                            CsvToBean<ItemReportCsv> csvToBean = null;
                            try {
                                HeaderColumnNameMappingStrategy<ItemReportCsv> strategy = new HeaderColumnNameMappingStrategy<>();
                                strategy.setType(ItemReportCsv.class);
                                //csvToBean = new CsvToBeanBuilder<ItemReportCsv>(br).withMappingStrategy(strategy).build();
                                // 创建一个新的 CSVReader 实例并解析文件
                                br = new BufferedReader(new InputStreamReader(zipFile.getInputStream(zipEntry)));  // 新建 BufferedReader
                                csvToBean = new CsvToBeanBuilder<ItemReportCsv>(br)
                                        .withMappingStrategy(strategy)
                                        .withSeparator(',')
                                        .withQuoteChar('"')
                                        .withSkipLines(0)  // 可以跳过无效或错误的行
                                        .withIgnoreLeadingWhiteSpace(true)  // 忽略行前的空格
                                        .build();
                                List<ItemReportCsv> reportCsvs = csvToBean.parse();
                                List<ReportItem> reportItemList = new ArrayList<>();
                                ReportItem reportItem = null;
                                for (ItemReportCsv itemReportCsv:reportCsvs) {
                                    reportItem = new ReportItem();
                                    reportItem.setAuthId(shopAuth.getAuthId());
                                    BeanUtils.copyProperties(itemReportCsv, reportItem);
                                    reportItem.setRequestId(requestId);
                                    reportItemList.add(reportItem);
                                }
                                return reportItemList;

                            } catch (Exception e) {
                                log.error("error :{}" , e.getMessage() );
                            } finally {
                                file.delete();
                            }
                        }
                    }
                }
            }
            // 如果没有找到CSV文件，返回一个空的报告项目列表
            return Collections.emptyList();
        } catch (IOException e) {
            throw new UtilException(e);
        } finally {
            //file.delete();
            IoUtil.close(inputStream);

        }
    }
    public static String requestPut(String url, Map<String, Object> paramMap,String jsonBody,ShopAuth shopAuth) {
        Map<String, String> headers = getHeaders(null,Method.PUT,null,shopAuth);

        // post请求拼接参数
        if (paramMap != null && paramMap.size() > 0) {
            if (url.indexOf("?") > 0) {
                url = url + "&" + HttpUtil.toParams(paramMap);
            } else {
                url = url + "?" + HttpUtil.toParams(paramMap);
            }
        }

        HttpResponse response = HttpRequest.put(url)
                .addHeaders(headers)
                .body(jsonBody)
                .execute();

        if (HttpStatus.HTTP_OK == response.getStatus()) {
            log.info("接口响应数据response：{}", response);
            log.info("接口响应数据response.body()：{}", response.body());

            return response.body();
        } else {
            String errorMessage = "调用Walmart API 异常: 状态码: " + response.getStatus() + ", 响应内容: " + response.body();
            log.error("调用Walmart API 错误");
            throw new ServiceException(errorMessage);  // 抛出带有错误消息的异常
        }
    }

    // 修改方法返回类型为byte[]
    public static byte[] requestPostShipmentLabel(String url, Map<String, Object> paramMap, String jsonBody, ShopAuth shopAuth) {
        Map<String, String> headers = getHeaders(null, Method.POST, null, shopAuth);

        // 强制指定接收二进制响应（关键）
        headers.put("Accept", "application/pdf");

        // 构建请求
        HttpResponse response = HttpRequest.post(url)
                .addHeaders(headers)
                .body(jsonBody)
                .execute();

        if (response.getStatus() == HttpStatus.HTTP_OK) {
            // 获取二进制内容（核心改动）
            byte[] pdfBytes = response.bodyBytes();
            log.info("成功获取PDF数据，长度: {} bytes", pdfBytes.length);
            return pdfBytes;
        } else {
            throw new ServiceException("API异常: " + response.getStatus());
        }
    }
}
